Este notebook visa usar vários aprendizados em Python e suas bibliotecas, para análise dos dados climáticos disponíveis em https://bdmep.inmet.gov.br/, incluindo análise visual por mapas
Um processamento básico foi feito sobre os dados originais (que são médias diárias registradas por várias estações em funcionamento no Brasil). Este processamento foi salvo em arquivos separados:
- inmet_2022_daily_observations.csv
- inmet_2022_stations
Ao longo do exercício, alguns artigos jornalísticos relatando eventos anormais são referenciados, para tentar achar nos dados, as indicações reportadas por estes artigos.
import pandas as pd
import folium
Os arquivos disponíveis são registros obtidos por 567 estações espalhadas pelo Brasil, um arquivo por estação. Cada registro destes arquivos correspondem à média horária de várias variáveis climáticas, todas detalhando Pressão, Temperatura, Humidade, Ventos, Precipitação e Radiação.
Eu decidi trabalhar com DataFrames em separado: Medições e Estações usando como chave o código da estação, quando necessário. Porém, sugiro mantê-los unificados, para menor esforço.
Na carga, eu agrupei-os por dia, usando as médias de cada variável, e salvando nos arquivos processados, se necessário.
Um dos problemas destes arquivos é que eles não contém medições em todos os dias de 2022. Para simplificação, eu os desconsiderei, quando possível.
numeric_features=["PRECIPITAÇÃO TOTAL, HORÁRIO (mm)",
"PRESSAO ATMOSFERICA AO NIVEL DA ESTACAO, HORARIA (mB)",
"PRESSÃO ATMOSFERICA MAX.NA HORA ANT. (AUT) (mB)",
"PRESSÃO ATMOSFERICA MIN. NA HORA ANT. (AUT) (mB)",
"RADIACAO GLOBAL (Kj/m²)",
"TEMPERATURA DO AR - BULBO SECO, HORARIA (°C)",
"TEMPERATURA DO PONTO DE ORVALHO (°C)",
"TEMPERATURA MÁXIMA NA HORA ANT. (AUT) (°C)",
"TEMPERATURA MÍNIMA NA HORA ANT. (AUT) (°C)",
"TEMPERATURA ORVALHO MIN. NA HORA ANT. (AUT) (°C)",
"UMIDADE REL. MAX. NA HORA ANT. (AUT) (%)",
"UMIDADE REL. MIN. NA HORA ANT. (AUT) (%)",
"UMIDADE RELATIVA DO AR, HORARIA (%)",
"VENTO, DIREÇÃO HORARIA (gr) (° (gr))",
"VENTO, RAJADA MAXIMA (m/s)",
"VENTO, VELOCIDADE HORARIA (m/s)"
]
wheather_mean_parameters = {
"Precipitação":"PRECIPITAÇÃO TOTAL, HORÁRIO (mm)_mean",
"Umidade":"UMIDADE RELATIVA DO AR, HORARIA (%)_mean",
"Pressão":"PRESSAO ATMOSFERICA AO NIVEL DA ESTACAO, HORARIA (mB)_mean",
"Temperatura":"TEMPERATURA DO AR - BULBO SECO, HORARIA (°C)_mean",
"Vento":"VENTO, VELOCIDADE HORARIA (m/s)_mean",
"Radiação":"RADIACAO GLOBAL (Kj/m²)_mean"
}
wheather_max_parameters = {
"Precipitação":"PRECIPITAÇÃO TOTAL, HORÁRIO (mm)",
"Umidade":"UMIDADE REL. MAX. NA HORA ANT. (AUT) (%)",
"Pressão":"PRESSÃO ATMOSFERICA MAX.NA HORA ANT. (AUT) (mB)",
"Temperatura":"TEMPERATURA MÁXIMA NA HORA ANT. (AUT) (°C)",
"Vento":"VENTO, RAJADA MAXIMA (m/s)",
"Radiação":"RADIACAO GLOBAL (Kj/m²)"
}
TEMP_INDICATORS = {
"mean":
[
"TEMPERATURA DO AR - BULBO SECO, HORARIA (°C)_mean",
"TEMPERATURA DO PONTO DE ORVALHO (°C)_mean",
"TEMPERATURA MÁXIMA NA HORA ANT. (AUT) (°C)_mean",
"TEMPERATURA MÍNIMA NA HORA ANT. (AUT) (°C)_mean",
"TEMPERATURA ORVALHO MIN. NA HORA ANT. (AUT) (°C)_mean"
],
"min":
[
"TEMPERATURA MÍNIMA NA HORA ANT. (AUT) (°C)_min",
"TEMPERATURA ORVALHO MIN. NA HORA ANT. (AUT) (°C)_min"
],
"max":
[
"TEMPERATURA MÁXIMA NA HORA ANT. (AUT) (°C)_max",
"TEMPERATURA ORVALHO MIN. NA HORA ANT. (AUT) (°C)_max"
]
}
PRESSURE_INDICATORS = [
"PRESSAO ATMOSFERICA AO NIVEL DA ESTACAO, HORARIA (mB)",
"PRESSÃO ATMOSFERICA MAX.NA HORA ANT. (AUT) (mB)",
"PRESSÃO ATMOSFERICA MIN. NA HORA ANT. (AUT) (mB)",
]
RADIATION_INDICATORS = ["RADIACAO GLOBAL (Kj/m²)"]
HUMIDITY_INDICATORS = [
"UMIDADE REL. MAX. NA HORA ANT. (AUT) (%)",
"UMIDADE REL. MAX. NA HORA ANT. (AUT) (%)",
"UMIDADE REL. MIN. NA HORA ANT. (AUT) (%)",
"UMIDADE RELATIVA DO AR, HORARIA (%)"
]
WIND_INDICATORS = [
"VENTO, DIREÇÃO HORARIA (gr) (° (gr))",
"VENTO, RAJADA MAXIMA (m/s)",
"VENTO, VELOCIDADE HORARIA (m/s)"
]
data_dir = "../data/INMET_2022/"
inmet_encoding='ISO-8859-1'
inmet_delimiter=";"
def load_files(filename):
full_name = data_dir + filename
#print (f"loading {filename} ...")
station_df = pd.read_csv(
full_name,
encoding=inmet_encoding,
delimiter=inmet_delimiter,
decimal=",",
skiprows=8)
# Observations
station_daily_df = station_df.groupby(by="Data")[numeric_features].agg(['mean','min','max'])
# Station parameters
idx=1
params = []
with open(full_name) as file:
for line in file:
line = line.rstrip("\n")
param = line.split(":;")
params.append(param)
idx+=1
if idx == 9:
break
station_daily_df["CODIGO (WMO)"] = params[3][1]
#station_params_df = pd.DataFrame(columns=['REGIAO','UF','ESTACAO','CODIGO (WMO)','LATITUDE','LONGITUDE','ALTITUDE','DATA DE FUNDACAO'])
param_row={
params[0][0]:params[0][1],
params[1][0]:params[1][1],
params[2][0]:params[2][1],
params[3][0]:params[3][1],
params[4][0]:float(params[4][1].replace(",",".")),
params[5][0]:float(params[5][1].replace(",",".")),
params[6][0]:float(params[6][1].replace(",",".")),
params[7][0]:params[7][1],
}
station_params_df = pd.DataFrame([param_row])
#station_params_df = pd.concat([station_params_df,df_dictionary])
return station_daily_df,station_params_df
# Skip this cell, if it was done already and you decide to use the processed files:
# inmet_2022_daily_observations.csv
# inmet_2022_stations.csv
import os
station_obs = pd.DataFrame()
station_params = pd.DataFrame()
files = os.listdir(data_dir)
for file in files:
obs_df,params_df = load_files(file)
station_obs = pd.concat([station_obs,obs_df])
station_params = pd.concat([station_params,params_df])
new_columns = [col[0] + "_" + col[1] if col[1] in ['mean','min','max'] else col[0] for col in station_obs.columns]
station_obs.columns = new_columns
station_obs.dropna(inplace=True)
station_obs.to_csv('../data/inmet_2022_daily_observations.csv')
station_params.to_csv('../data/inmet_2022_stations.csv', index=False)
station_obs=pd.read_csv('../data/inmet_2022_daily_observations.csv',index_col="Data")
station_params = pd.read_csv('../data/inmet_2022_stations.csv')
temp_avg = station_obs.sort_values("TEMPERATURA DO AR - BULBO SECO, HORARIA (°C)_mean",ascending=True)[TEMP_INDICATORS['mean'] + ["CODIGO (WMO)"]]
temp_avg = pd.merge(temp_avg,station_params,how='left',on="CODIGO (WMO)")
temp_avg.head(3)
| TEMPERATURA DO AR - BULBO SECO, HORARIA (°C)_mean | TEMPERATURA DO PONTO DE ORVALHO (°C)_mean | TEMPERATURA MÁXIMA NA HORA ANT. (AUT) (°C)_mean | TEMPERATURA MÍNIMA NA HORA ANT. (AUT) (°C)_mean | TEMPERATURA ORVALHO MIN. NA HORA ANT. (AUT) (°C)_mean | CODIGO (WMO) | REGIAO | UF | ESTACAO | LATITUDE | LONGITUDE | ALTITUDE | DATA DE FUNDACAO | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 0.670833 | -3.683333 | 1.166667 | 0.200000 | -4.216667 | A815 | S | SC | SAO JOAQUIM | -28.27564 | -49.934617 | 1400.06 | 12/04/08 |
| 1 | 1.100000 | -3.654167 | 1.825000 | 0.612500 | -4.329167 | A815 | S | SC | SAO JOAQUIM | -28.27564 | -49.934617 | 1400.06 | 12/04/08 |
| 2 | 1.412500 | -4.037500 | 1.912500 | 0.820833 | -4.641667 | A815 | S | SC | SAO JOAQUIM | -28.27564 | -49.934617 | 1400.06 | 12/04/08 |
temp_avg.tail(3)
| TEMPERATURA DO AR - BULBO SECO, HORARIA (°C)_mean | TEMPERATURA DO PONTO DE ORVALHO (°C)_mean | TEMPERATURA MÁXIMA NA HORA ANT. (AUT) (°C)_mean | TEMPERATURA MÍNIMA NA HORA ANT. (AUT) (°C)_mean | TEMPERATURA ORVALHO MIN. NA HORA ANT. (AUT) (°C)_mean | CODIGO (WMO) | REGIAO | UF | ESTACAO | LATITUDE | LONGITUDE | ALTITUDE | DATA DE FUNDACAO | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 123022 | 36.433333 | 11.400000 | 37.400000 | 36.100000 | 11.150000 | A331 | NE | PI | SAO JOAO DO PIAUI | -8.364444 | -42.252500 | 231.00 | 26/08/07 |
| 123023 | 36.700000 | 17.255556 | 37.800000 | 35.077778 | 16.488889 | A869 | S | PR | CIDADE GAUCHA | -23.359167 | -52.931944 | 365.79 | 11/03/08 |
| 123024 | 36.800000 | 10.750000 | 38.133333 | 36.100000 | 8.666667 | A331 | NE | PI | SAO JOAO DO PIAUI | -8.364444 | -42.252500 | 231.00 | 26/08/07 |
temp_min = station_obs.groupby("CODIGO (WMO)").agg("min")[TEMP_INDICATORS['min']]
temp_min = temp_min.sort_values("TEMPERATURA MÍNIMA NA HORA ANT. (AUT) (°C)_min",ascending=True).head(10)
temp_min = pd.merge(temp_min,station_params,how='left',on="CODIGO (WMO)")
temp_min
| CODIGO (WMO) | TEMPERATURA MÍNIMA NA HORA ANT. (AUT) (°C)_min | TEMPERATURA ORVALHO MIN. NA HORA ANT. (AUT) (°C)_min | REGIAO | UF | ESTACAO | LATITUDE | LONGITUDE | ALTITUDE | DATA DE FUNDACAO | |
|---|---|---|---|---|---|---|---|---|---|---|
| 0 | A875 | -3.9 | -8.8 | S | PR | GENERAL CARNEIRO | -26.398611 | -51.353611 | 1009.01 | 30/04/08 |
| 1 | A815 | -3.9 | -19.7 | S | SC | SAO JOAQUIM | -28.275640 | -49.934617 | 1400.06 | 12/04/08 |
| 2 | A880 | -2.7 | -5.8 | S | RS | VACARIA | -28.513602 | -50.882738 | 969.89 | 26/04/08 |
| 3 | A831 | -2.5 | -5.7 | S | RS | QUARAI | -30.368578 | -56.437115 | 113.05 | 17/10/07 |
| 4 | A874 | -2.3 | -9.8 | S | PR | SAO MATEUS DO SUL | -25.835556 | -50.368889 | 780.21 | 17/04/11 |
| 5 | A894 | -2.2 | -6.5 | S | RS | SERAFINA CORREA | -28.704722 | -51.870833 | 545.00 | 01/04/16 |
| 6 | A897 | -2.1 | -7.9 | S | RS | CAMBARA DO SUL | -29.049167 | -50.149722 | 1017.00 | 24/11/16 |
| 7 | A828 | -1.7 | -4.0 | S | RS | ERECHIM | -27.657778 | -52.305833 | 777.08 | 25/11/06 |
| 8 | A879 | -1.6 | -6.9 | S | RS | CANELA | -29.368889 | -50.827222 | 830.93 | 23/08/08 |
| 9 | A898 | -1.5 | -4.8 | S | SC | CAMPOS NOVOS | -27.388611 | -51.215833 | 963.00 | 15/02/19 |
temp_max = station_obs.groupby("CODIGO (WMO)").agg("max")[TEMP_INDICATORS['max']]
temp_max = temp_max.sort_values("TEMPERATURA MÁXIMA NA HORA ANT. (AUT) (°C)_max",ascending=False).head(10)
temp_max = pd.merge(temp_max,station_params,how='left',on="CODIGO (WMO)")
temp_max
| CODIGO (WMO) | TEMPERATURA MÁXIMA NA HORA ANT. (AUT) (°C)_max | TEMPERATURA ORVALHO MIN. NA HORA ANT. (AUT) (°C)_max | REGIAO | UF | ESTACAO | LATITUDE | LONGITUDE | ALTITUDE | DATA DE FUNDACAO | |
|---|---|---|---|---|---|---|---|---|---|---|
| 0 | A809 | 42.9 | 24.4 | S | RS | URUGUAIANA | -29.839870 | -57.081899 | 74.29 | 28/09/06 |
| 1 | A830 | 42.2 | 23.8 | S | RS | SAO BORJA | -28.650000 | -56.016389 | 81.08 | 21/07/07 |
| 2 | A852 | 42.0 | 23.5 | S | RS | SAO LUIZ GONZAGA | -28.417222 | -54.962500 | 245.50 | 25/07/07 |
| 3 | A882 | 41.7 | 23.8 | S | RS | TEUTONIA | -29.449167 | -51.823333 | 81.00 | 04/10/12 |
| 4 | A831 | 41.5 | 23.0 | S | RS | QUARAI | -30.368578 | -56.437115 | 113.05 | 17/10/07 |
| 5 | A724 | 41.4 | 23.6 | CO | MS | CORUMBA | -18.996667 | -57.637500 | 111.73 | 26/10/06 |
| 6 | A354 | 41.1 | 24.1 | NE | PI | OEIRAS | -6.974167 | -42.146944 | 154.03 | 22/07/08 |
| 7 | A326 | 41.1 | 24.7 | NE | PI | BOM JESUS DO PIAUI | -9.083333 | -44.326389 | 296.00 | 17/07/07 |
| 8 | A826 | 40.9 | 24.1 | S | RS | ALEGRETE | -29.709167 | -55.525556 | 120.88 | 28/09/06 |
| 9 | A833 | 40.9 | 22.4 | S | RS | SANTIAGO | -29.191599 | -54.885653 | 390.03 | 04/02/09 |
import leafmap.leafmap as leafmap
Map = leafmap.Map(center=[-15, -48], zoom=4)
#Map.add_xy_data(station_params, x="LONGITUDE", y="LATITUDE", layer_name="INMET Stations")
Map.add_points_from_xy(
station_params,
x="LONGITUDE",
y="LATITUDE",
#color_column='region',
icon_names=['gear', 'map', 'leaf', 'globe'],
spin=True,
add_legend=True,
)
Map
Map(center=[-15, -48], controls=(ZoomControl(options=['position', 'zoom_in_text', 'zoom_in_title', 'zoom_out_t…
year_avg_temp = station_obs.groupby("CODIGO (WMO)")[[("TEMPERATURA DO AR - BULBO SECO, HORARIA (°C)_mean")]].mean()
year_avg_temp = pd.merge(year_avg_temp, station_params, how='left', on='CODIGO (WMO)')
year_avg_temp = year_avg_temp[year_avg_temp["TEMPERATURA DO AR - BULBO SECO, HORARIA (°C)_mean"].notna()]
m = folium.Map([-15, -48], zoom_start=4)
for i in range(0,len(year_avg_temp)):
if (year_avg_temp.iloc[i]['TEMPERATURA DO AR - BULBO SECO, HORARIA (°C)_mean']) <= 15:
station_color = "green"
elif year_avg_temp.iloc[i]['TEMPERATURA DO AR - BULBO SECO, HORARIA (°C)_mean'] <= 20:
station_color = "blue"
elif year_avg_temp.iloc[i]['TEMPERATURA DO AR - BULBO SECO, HORARIA (°C)_mean'] <= 27:
station_color = "gray"
elif year_avg_temp.iloc[i]['TEMPERATURA DO AR - BULBO SECO, HORARIA (°C)_mean'] <= 30:
station_color = "red"
else:
station_color = "black"
folium.Marker(
location=[year_avg_temp.iloc[i]['LATITUDE'], year_avg_temp.iloc[i]['LONGITUDE']],
popup=round(year_avg_temp.iloc[i]['TEMPERATURA DO AR - BULBO SECO, HORARIA (°C)_mean'],1),
#icon=folium.DivIcon(html=f"""<div style="font-family: courier new; color: {station_color}">{year_avg_temp.iloc[i]['temp_str']}</div>""")
icon=folium.Icon(color=station_color),
).add_to(m)
m
import geopandas as gpd
import os
CONDA_PREFIX = r"C:\Users\hcord\anaconda3\envs\geo"
os.environ['GDAL_DATA'] = os.environ['CONDA_PREFIX'] + r'\Library\share\gdal'
code_df = station_obs.copy()
code_df = pd.merge(code_df, station_params, how='left', on='CODIGO (WMO)')
uf_temp_avg = code_df.groupby("UF")[["TEMPERATURA DO AR - BULBO SECO, HORARIA (°C)_mean"]].agg("mean").reset_index()
m_states = folium.Map(location=(-15, -48), zoom_start=4, tiles="cartodb positron")
folium.Choropleth(
geo_data="../data/Brazil.json",
data=code_df,
columns=["UF", "TEMPERATURA DO AR - BULBO SECO, HORARIA (°C)_mean"],
key_on="feature.properties.UF",
fill_color="RdYlGn_r",
fill_opacity=0.8,
line_opacity=0.3,
nan_fill_color="white",
).add_to(m_states)
# Mark the top 10 locations of highest temps
for index, row in temp_max.iterrows():
folium.Marker(
location=[row['LATITUDE'], row['LONGITUDE']],
popup=row['TEMPERATURA MÁXIMA NA HORA ANT. (AUT) (°C)_max'],
icon=folium.Icon(color="red"),
).add_to(m_states)
# Mark the top 10 locations of lowest temps
for index, row in temp_min.iterrows():
folium.Marker(
location=[row['LATITUDE'], row['LONGITUDE']],
popup=row['TEMPERATURA MÍNIMA NA HORA ANT. (AUT) (°C)_min'],
icon=folium.Icon(color="green"),
).add_to(m_states)
m_states
Remember that these highest and lowest occurr in different times. Eventhough, it is surprising the the state of Rio Grande do Sul present most of both metrics
In 2022 Brazil has experienced unusual/extreme meteorological scenarios. According to https://www.tempo.com/noticias/actualidade/retrospectiva-2022-relembre-os-eventos-climaticos-que-marcaram-o-ano-eventos-extremos-tempo-severo-onda-de-frio.html, these are the most relevant:
station_full = pd.merge(station_obs, station_params, how='inner', on='CODIGO (WMO)')
# Total per year
#total_anual_precip_per_state = pd.merge(station_obs, station_params, how='inner', on='CODIGO (WMO)')
states_highest_precip = station_full.groupby("UF")[["PRECIPITAÇÃO TOTAL, HORÁRIO (mm)_mean"]].mean().sort_values("PRECIPITAÇÃO TOTAL, HORÁRIO (mm)_mean",ascending=False)
states_highest_precip.head(4)
| PRECIPITAÇÃO TOTAL, HORÁRIO (mm)_mean | |
|---|---|
| UF | |
| AC | 0.281539 |
| AP | 0.279640 |
| AM | 0.249090 |
| PA | 0.237956 |
# Total per year - Average
stations_highest_precip = station_full.loc[(station_full["UF"].isin(["PA","AC","RJ","SC"]))]
stations_highest_precip = stations_highest_precip.groupby("ESTACAO")[["PRECIPITAÇÃO TOTAL, HORÁRIO (mm)_mean"]].mean().sort_values("PRECIPITAÇÃO TOTAL, HORÁRIO (mm)_mean",ascending=False)
stations_highest_precip.head(10)
| PRECIPITAÇÃO TOTAL, HORÁRIO (mm)_mean | |
|---|---|
| ESTACAO | |
| BREVES | 0.700238 |
| BOM JARDIM DA SERRA - MORRO DA IGREJA | 0.699762 |
| PARAGOMINAS | 0.561582 |
| CAPITAO POCO | 0.533280 |
| SERRA DOS CARAJAS | 0.471385 |
| BELEM | 0.407782 |
| TERESOPOLIS-PARQUE NACIONAL | 0.369740 |
| RIO BRANCO | 0.345753 |
| NOVO HORIZONTE | 0.342969 |
| BRAGANCA | 0.326365 |
# Total per year - Sum
stations_highest_precip = station_full.loc[(station_full["UF"].isin(["PA","AC","RJ","SC"]))]
stations_highest_precip = stations_highest_precip.groupby("ESTACAO")[["PRECIPITAÇÃO TOTAL, HORÁRIO (mm)_mean"]].sum().sort_values("PRECIPITAÇÃO TOTAL, HORÁRIO (mm)_mean",ascending=False)
pd.merge(stations_highest_precip.reset_index(),station_params,how="left",on="ESTACAO").sort_values("PRECIPITAÇÃO TOTAL, HORÁRIO (mm)_mean",ascending=False)[["ESTACAO","PRECIPITAÇÃO TOTAL, HORÁRIO (mm)_mean","REGIAO","UF"]].head(10)
| ESTACAO | PRECIPITAÇÃO TOTAL, HORÁRIO (mm)_mean | REGIAO | UF | |
|---|---|---|---|---|
| 0 | TERESOPOLIS-PARQUE NACIONAL | 132.366785 | SE | RJ |
| 1 | ANGRA DOS REIS | 115.022609 | SE | RJ |
| 2 | BELEM | 114.994438 | N | PA |
| 3 | ITAPOA | 108.107971 | S | SC |
| 4 | DIONISIO CERQUEIRA | 100.526394 | S | SC |
| 5 | JOACABA | 97.184139 | S | SC |
| 6 | CASTANHAL | 97.018615 | N | PA |
| 7 | CAMPOS NOVOS | 96.465048 | S | SC |
| 8 | PARQUE ESTADUAL CHANDLESS | 96.083246 | N | AC |
| 9 | NOVA FRIBURGO - SALINAS | 95.283333 | SE | RJ |
# Total per year
#avg_hum_per_state = pd.merge(station_obs, station_params, how='inner', on='CODIGO (WMO)')
states_avg_hum = station_full.groupby("UF")[["UMIDADE RELATIVA DO AR, HORARIA (%)_mean"]].mean().sort_values("UMIDADE RELATIVA DO AR, HORARIA (%)_mean",ascending=True)
states_avg_hum.head(4)
| UMIDADE RELATIVA DO AR, HORARIA (%)_mean | |
|---|---|
| UF | |
| RO | 47.355560 |
| SE | 58.566048 |
| PI | 60.550638 |
| RN | 61.668510 |
# Total per year
stations_lowest_hum = station_full.loc[(station_full["UF"].isin(["GO","DF","MS","SP"]))]
stations_lowest_hum = stations_lowest_hum.groupby("ESTACAO")[["UMIDADE RELATIVA DO AR, HORARIA (%)_mean"]].mean().sort_values("UMIDADE RELATIVA DO AR, HORARIA (%)_mean",ascending=True)
pd.merge(stations_lowest_hum.reset_index(),station_params,how="left",on="ESTACAO").sort_values("UMIDADE RELATIVA DO AR, HORARIA (%)_mean",ascending=True)[["ESTACAO","UMIDADE RELATIVA DO AR, HORARIA (%)_mean","REGIAO","UF"]].head(10)
| ESTACAO | UMIDADE RELATIVA DO AR, HORARIA (%)_mean | REGIAO | UF | |
|---|---|---|---|---|
| 0 | CASSILANDIA | 47.430481 | CO | MS |
| 1 | POSSE | 48.993281 | CO | GO |
| 2 | CORUMBA | 52.650113 | CO | MS |
| 3 | PARANAIBA | 55.431436 | CO | MS |
| 4 | JALES | 56.516019 | SE | SP |
| 5 | ARIRANHA | 57.039319 | SE | SP |
| 6 | GOIANESIA | 57.802712 | CO | GO |
| 7 | GOIANIA | 58.564266 | CO | GO |
| 8 | CATALAO | 58.678764 | CO | GO |
| 9 | MONTE ALEGRE DE GOIAS | 58.823740 | CO | GO |
# Total per year
#temps_per_state = pd.merge(station_obs, station_params, how='inner', on='CODIGO (WMO)')
temps_per_state = station_full.groupby("UF")[["TEMPERATURA DO AR - BULBO SECO, HORARIA (°C)_mean"]].mean().sort_values("TEMPERATURA DO AR - BULBO SECO, HORARIA (°C)_mean",ascending=False)
temps_per_state.head(4)
| TEMPERATURA DO AR - BULBO SECO, HORARIA (°C)_mean | |
|---|---|
| UF | |
| RO | 30.050422 |
| RN | 28.662405 |
| PI | 27.728511 |
| MA | 27.249262 |
# Total per year
stations_high_temps = station_full.loc[(station_full["UF"].isin(["PA","AM","AC","MT"]))]
stations_high_temps = stations_high_temps.groupby("ESTACAO")[["TEMPERATURA DO AR - BULBO SECO, HORARIA (°C)_mean"]].mean().sort_values("TEMPERATURA DO AR - BULBO SECO, HORARIA (°C)_mean",ascending=False)
pd.merge(stations_high_temps.reset_index(),station_params,how="left",on="ESTACAO").sort_values("TEMPERATURA DO AR - BULBO SECO, HORARIA (°C)_mean",ascending=False)[["ESTACAO","TEMPERATURA DO AR - BULBO SECO, HORARIA (°C)_mean","REGIAO","UF"]].head(10)
| ESTACAO | TEMPERATURA DO AR - BULBO SECO, HORARIA (°C)_mean | REGIAO | UF | |
|---|---|---|---|---|
| 0 | XINGUARA | 29.125891 | N | PA |
| 1 | SAO FELIX DO ARAGUAIA | 28.151389 | CO | MT |
| 2 | CASTANHAL | 27.941016 | N | PA |
| 3 | TUCURUI | 27.772724 | N | PA |
| 4 | ITAITUBA | 27.615391 | N | PA |
| 5 | CUIABA | 27.600052 | CO | MT |
| 6 | REDENCAO | 27.595255 | N | PA |
| 7 | MANAUS | 27.582519 | N | AM |
| 8 | SERRA NOVA DOURADA | 27.424863 | CO | MT |
| 9 | MANACAPURU | 27.210845 | N | AM |
Para facilitar comparações, criei funções em que é possível exibir parâmetros ao longo do ano para ESTACAO, ESTADO, ou BRASIL, ou inclusive, apresentá-los em pares, lado a lado (ESTACAO + ESTADO, ou ESTACAO + PAIS, ou ESTADO + PAIS)
UFs = ["AC","AL","AP","AM","BA","CE","DF","ES","GO","MA","MT","MS","MG","PA","PB","PR","PE","PI","RJ","RN","RS","RO","RR","SC","SP","SE","TO"]
def prepare_df (*args):
presentation_df = pd.DataFrame()
if (len(args)==1):
target=args[0]
if target == "BRASIL":
# presentation_df = tudo
#temp_df = pd.merge(station_obs.reset_index(), station_params, how='left', on='CODIGO (WMO)').set_index('Data')
#grouped_df = temp_df.groupby([temp_df.index])[["TEMPERATURA DO AR - BULBO SECO, HORARIA (°C)_mean"]].agg("mean").reset_index().set_index('Data')
presentation_df = station_obs.groupby([station_obs.index])[list(wheather_mean_parameters.values())].agg("mean").reset_index().set_index('Data')
elif target in UFs:
# adicionar estado em presentation_df
temp_df = pd.merge(station_obs.reset_index(), station_params.loc[station_params['UF'] == target], how='inner', on='CODIGO (WMO)').set_index('Data')
grouped_df = temp_df.groupby([temp_df.index,"UF"])[list(wheather_mean_parameters.values())].agg("mean").reset_index().set_index('Data')
presentation_df = pd.concat([presentation_df,grouped_df])
else:
# adicionar estação em presentation_df
temp_df = pd.merge(station_obs.reset_index(), station_params.loc[station_params['ESTACAO'] == target], how='inner', on='CODIGO (WMO)').set_index('Data')
presentation_df = pd.concat([presentation_df,temp_df])
else:
target_1 = args[0]
target_2 = args[1]
if target_1 == "BRASIL" or target_2 == "BRASIL" :
# presentation_df = tudo
#temp_df = pd.merge(station_obs.reset_index(), station_params, how='left', on='CODIGO (WMO)').set_index('Data')
#grouped_df = temp_df.groupby([temp_df.index])[["TEMPERATURA DO AR - BULBO SECO, HORARIA (°C)_mean"]].agg("mean").reset_index().set_index('Data')
presentation_df = station_obs.groupby([station_obs.index])[list(wheather_mean_parameters.values())].agg("mean").reset_index().set_index('Data')
elif target_1 in UFs and target_2 in UFs:
# adicionar estado em presentation_df
temp1_df = pd.merge(station_obs.reset_index(), station_params.loc[station_params['UF'] == target_1], how='inner', on='CODIGO (WMO)').set_index('Data')
grouped1_df = temp1_df.groupby([temp1_df.index,"UF"])[list(wheather_mean_parameters.values())].agg("mean").reset_index().set_index('Data')
temp2_df = pd.merge(station_obs.reset_index(), station_params.loc[station_params['UF'] == target_2], how='inner', on='CODIGO (WMO)').set_index('Data')
grouped2_df = temp2_df.groupby([temp2_df.index,"UF"])[list(wheather_mean_parameters.values())].agg("mean").reset_index().set_index('Data')
presentation_df = pd.concat([grouped1_df,grouped2_df])
elif ((not target_1 in UFs) and (not target_2 in UFs)):
# adicionar estação em presentation_df
temp1_df = pd.merge(station_obs.reset_index(), station_params.loc[station_params['ESTACAO'] == target_1], how='inner', on='CODIGO (WMO)').set_index('Data')
temp2_df = pd.merge(station_obs.reset_index(), station_params.loc[station_params['ESTACAO'] == target_2], how='inner', on='CODIGO (WMO)').set_index('Data')
presentation_df = pd.concat([temp1_df,temp2_df])
else:
presentation_df = pd.merge(station_obs.reset_index(), station_params.loc[station_params['UF'] == target_1], how='inner', on='CODIGO (WMO)').set_index('Data')
return presentation_df
import plotly.express as px
from plotly.subplots import make_subplots
import plotly.graph_objects as go
from datetime import datetime
def plot_panel(*args):
df = args[0]
if (len(args) == 3):
df = args[0]
target_1 = args[1]
target_2 = args[2]
# Split df into df_1 and df_2 according the targets
if target_1 == "BRASIL":
df1 = df.copy()
else:
if target_1 in UFs and target_2 in UFs:
df1 = df.loc[df["UF"] == target_1]
elif ((target_1 in UFs) and (not target_2 in UFs)):
df1 = df.loc[df["UF"] == target_1].groupby([df.index,"UF"])[list(wheather_mean_parameters.values())].agg("mean").reset_index().set_index('Data')
else:
df1 = df.loc[df["ESTACAO"] == target_1]
if target_2 == "BRASIL":
df2 = df.copy()
else:
if target_2 in UFs:
df2 = df.loc[df["UF"] == target_2]
else:
df2 = df.loc[df["ESTACAO"] == target_2]
l = [key for key in wheather_mean_parameters.keys()]
fl = []
for i in l:
fl.append(i)
fl.append(i)
# Display both sets
fig = make_subplots(rows=6, cols=2,shared_xaxes=True,vertical_spacing=0.03,
subplot_titles=(fl)
)
# Set 1
for idx, param in enumerate(wheather_mean_parameters):
fig.append_trace(
go.Scatter(x=[datetime.strptime(date, "%Y/%m/%d").date().strftime("%m/%d") for date in df1.index],
y=df1[wheather_mean_parameters[param]]),
row=idx+1, col=1
)
# Set 2
for idx, param in enumerate(wheather_mean_parameters):
fig.append_trace(
go.Scatter(x=[datetime.strptime(date, "%Y/%m/%d").date().strftime("%m/%d") for date in df2.index],
y=df2[wheather_mean_parameters[param]]),
row=idx+1, col=2
)
chart_label = "Clima em " + target_1 + " e " + target_2 + " (valores médios) de " + str(df1.index.min()) + " a " + str(df1.index.max())
fig.update_layout(
height=800, width=900, title_text=chart_label,showlegend=False
)
fig.update_annotations(font_size=10)
fig.show()
elif (len(args) == 2):
df = args[0]
fig = make_subplots(rows=6, cols=1,shared_xaxes=True,vertical_spacing=0.03,
subplot_titles=([key for key in wheather_mean_parameters.keys()]))
for idx, param in enumerate(wheather_mean_parameters):
fig.append_trace(
go.Scatter(x=[datetime.strptime(date, "%Y/%m/%d").date().strftime("%m/%d") for date in df.index],
y=df[wheather_mean_parameters[param]]),
row=idx+1, col=1
)
chart_label = "Clima em " + args[1] + " (valores médios) de " + str(df.index.min()) + " a " + str(df.index.max())
fig.update_layout(
height=800, width=980, title_text=chart_label,showlegend=False
)
fig.update_annotations(font_size=10)
fig.show()
def plot_variables(*args):
if len(args) == 1:
df = prepare_df(args[0])
plot_panel(df,args[0])
elif len(args) == 2:
df = prepare_df(args[0],args[1])
plot_panel(df,args[0],args[1])
else:
print("Não suportado")
Observando as médias nacionais
plot_variables("BRASIL")
plot_variables("RJ")
plot_variables("SAO PAULO - MIRANTE")
Comparando 2 Estados
plot_variables("SP","RJ")
plot_variables("SP","SC")
plot_variables("SP","SAO PAULO - MIRANTE")
#plot_variables("SAO JOAQUIM","SAO PAULO - MIRANTE")
Itatiaia National Park reached very negative temperatures at the beginning of winter 2022, allowing the formation of two very rare meteorological phenomena. (images: Fluminense Climate Monitoring)
plot_variables("RJ","RESENDE")
Não observamos tal comportamento acima
We remember the tragic episode between the end of March and the beginning of April, when historical accumulations of 500 to 800 mm were added in just 5 days on the north coast of São Paulo and in the south of Rio de Janeiro, where, in Angra dos Reis, at least 15 people died.
plot_variables("BERTIOGA","ANGRA DOS REIS")
In order to verify this statement, we'll need to reload the original file, filtering ANGRA DOS REIS and BERTIOGA that are the target stations and aggregate by their sum
angra_file = data_dir + "/INMET_SE_RJ_A628_ANGRA DOS REIS_01-01-2022_A_31-12-2022.csv"
angra_df = pd.read_csv(
angra_file,
encoding=inmet_encoding,
delimiter=inmet_delimiter,
decimal=",",
skiprows=8)
bertioga_file = data_dir + "/INMET_SE_RJ_A628_ANGRA DOS REIS_01-01-2022_A_31-12-2022.csv"
bertioga_df = pd.read_csv(
bertioga_file,
encoding=inmet_encoding,
delimiter=inmet_delimiter,
decimal=",",
skiprows=8)
# Observations
angra_df = angra_df.groupby(by="Data")[["PRECIPITAÇÃO TOTAL, HORÁRIO (mm)"]].agg(['sum'])
angra_df = angra_df.loc[(angra_df.index>="2022/03/31") & (angra_df.index<="2022/04/06")]
angra_df[('PRECIPITAÇÃO TOTAL, HORÁRIO (mm)', 'sum')].sum()
bertioga_df = bertioga_df.groupby(by="Data")[["PRECIPITAÇÃO TOTAL, HORÁRIO (mm)"]].agg(['sum'])
bertioga_df = bertioga_df.loc[(bertioga_df.index>="2022/03/31") & (bertioga_df.index<="2022/04/06")]
bertioga_df[('PRECIPITAÇÃO TOTAL, HORÁRIO (mm)', 'sum')].sum()
angra_bert_df = pd.concat([angra_df,bertioga_df])
angra_bert_df.sum()
PRECIPITAÇÃO TOTAL, HORÁRIO (mm) sum 680.8 dtype: float64
Roberto Quental Coutinho, professor titular do departamento, afirma que, além das causas para os deslizamentos, o projeto analisa, também, os alagamentos e a quantidade de chuva que aconteceu em maio de 2022.
Pernambuco state, mainly Recife, has registered some severe rains. Let´s check
plot_variables("PE")
State averages show an increase level of humidity starting May, which corroborates the report. The most damaged area was Recife. Let´s see
plot_variables("RECIFE")
The RECIFE station (which is in Camaragibe, the most affected city) produce no records in 2022.
REGIAO:;NE
UF:;PE
ESTACAO:;RECIFE
CODIGO (WMO):;A301
LATITUDE:;-8,05916666
LONGITUDE:;-34,95916666
ALTITUDE:;11,3
DATA DE FUNDACAO:;22/12/04
Data;Hora UTC;PRECIPITAÇÃO TOTAL, HORÁRIO (mm);PRESSAO ATMOSFERICA AO NIVEL DA ESTACAO, HORARIA (mB);PRESSÃO ATMOSFERICA MAX.NA HORA ANT. (AUT) (mB);PRESSÃO ATMOSFERICA MIN. NA HORA ANT. (AUT) (mB);RADIACAO GLOBAL (Kj/m²);TEMPERATURA DO AR - BULBO SECO, HORARIA (°C);TEMPERATURA DO PONTO DE ORVALHO (°C);TEMPERATURA MÁXIMA NA HORA ANT. (AUT) (°C);TEMPERATURA MÍNIMA NA HORA ANT. (AUT) (°C);TEMPERATURA ORVALHO MAX. NA HORA ANT. (AUT) (°C);TEMPERATURA ORVALHO MIN. NA HORA ANT. (AUT) (°C);UMIDADE REL. MAX. NA HORA ANT. (AUT) (%);UMIDADE REL. MIN. NA HORA ANT. (AUT) (%);UMIDADE RELATIVA DO AR, HORARIA (%);VENTO, DIREÇÃO HORARIA (gr) (° (gr));VENTO, RAJADA MAXIMA (m/s);VENTO, VELOCIDADE HORARIA (m/s);
2022/01/01;0000 UTC;;;;;;;;;;;;;;;;;;
2022/01/01;0100 UTC;;;;;;;;;;;;;;;;;;
2022/01/01;0200 UTC;;;;;;;;;;;;;;;;;;
etc...
Ciclone extratropical favorece temporais em SC na manhã desta segunda-feira, alerta Defesa Civil
Risco é maior no Oeste. Pode ocorrer chuva intensa, raios, granizo e ventos que podem passar dos 70 km/h.
Nov 14th
Formação de ciclone deixa SC em alerta para rajadas de vento de até 100 km/h.
Ventos devem ser mais fortes no mar, de acordo com a Defesa Civil.
Sep 22nd
plot_variables("SC","SP")
plot_variables("Laguna - Farol de Santa Marta")
ms_to_kmh = lambda ms : ms/1000*3600
ms_to_kmh(15)
54.0
Vamos olhar para os dados originais, nestes locais, onde podemos retomar variáveis além das médias
laguna_file = data_dir + "/INMET_S_SC_A866_Laguna - Farol de Santa Marta_01-01-2022_A_31-12-2022.csv"
laguna_df = pd.read_csv(
laguna_file,
encoding=inmet_encoding,
delimiter=inmet_delimiter,
decimal=",",
skiprows=8)
laguna_df['ESTACAO'] = "Laguna"
urussanga_file = data_dir + "/INMET_S_SC_A814_URUSSANGA_01-01-2022_A_31-12-2022.csv"
urussanga_df = pd.read_csv(
urussanga_file,
encoding=inmet_encoding,
delimiter=inmet_delimiter,
decimal=",",
skiprows=8)
urussanga_df['ESTACAO'] = "Urussanga"
ararangua_file = data_dir + "/INMET_S_SC_A867_ARARANGUA_01-01-2022_A_31-12-2022.csv"
ararangua_df = pd.read_csv(
ararangua_file,
encoding=inmet_encoding,
delimiter=inmet_delimiter,
decimal=",",
skiprows=8)
ararangua_df['ESTACAO'] = "Ararangua"
# Observations
#laguna_df = laguna_df.groupby(by="Data")[["VENTO, RAJADA MAXIMA (m/s)"]].agg(['max'])
#laguna_df = laguna_df.loc[(laguna_df.index>="2022/03/31") & (laguna_df.index<="2022/04/06")]
#laguna_df[('VENTO, RAJADA MAXIMA (m/s)', 'max')].sum()
#urussanga_df = urussanga_df.groupby(by="Data")[["VENTO, RAJADA MAXIMA (m/s)"]].agg(['sum'])
#urussanga_df = urussanga_df.loc[(urussanga_df.index>="2022/03/31") & (urussanga_df.index<="2022/04/06")]
#urussanga_df[('VENTO, RAJADA MAXIMA (m/s)', 'sum')].sum()
#ararangua_df = ararangua_df.groupby(by="Data")[["VENTO, RAJADA MAXIMA (m/s)"]].agg(['sum'])
#ararangua_df = ararangua_df.loc[(ararangua_df.index>="2022/03/31") & (ararangua_df.index<="2022/04/06")]
#ararangua_df[('VENTO, RAJADA MAXIMA (m/s)', 'sum')].sum()
sc_severe_winds_df = pd.concat([laguna_df,urussanga_df,ararangua_df])
sc_severe_winds_df.sort_values(['VENTO, RAJADA MAXIMA (m/s)'],ascending=False).head(10)
| Data | Hora UTC | PRECIPITAÇÃO TOTAL, HORÁRIO (mm) | PRESSAO ATMOSFERICA AO NIVEL DA ESTACAO, HORARIA (mB) | PRESSÃO ATMOSFERICA MAX.NA HORA ANT. (AUT) (mB) | PRESSÃO ATMOSFERICA MIN. NA HORA ANT. (AUT) (mB) | RADIACAO GLOBAL (Kj/m²) | TEMPERATURA DO AR - BULBO SECO, HORARIA (°C) | TEMPERATURA DO PONTO DE ORVALHO (°C) | TEMPERATURA MÁXIMA NA HORA ANT. (AUT) (°C) | ... | TEMPERATURA ORVALHO MAX. NA HORA ANT. (AUT) (°C) | TEMPERATURA ORVALHO MIN. NA HORA ANT. (AUT) (°C) | UMIDADE REL. MAX. NA HORA ANT. (AUT) (%) | UMIDADE REL. MIN. NA HORA ANT. (AUT) (%) | UMIDADE RELATIVA DO AR, HORARIA (%) | VENTO, DIREÇÃO HORARIA (gr) (° (gr)) | VENTO, RAJADA MAXIMA (m/s) | VENTO, VELOCIDADE HORARIA (m/s) | Unnamed: 19 | ESTACAO | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 5514 | 2022/08/18 | 1800 UTC | 1.0 | 1007.3 | 1007.5 | 1006.3 | 227.6 | 13.9 | 11.2 | 14.5 | ... | 11.7 | 9.5 | 86.0 | 73.0 | 84.0 | 208.0 | 28.3 | 17.6 | NaN | Laguna |
| 5515 | 2022/08/18 | 1900 UTC | 0.2 | 1008.6 | 1008.8 | 1006.9 | 185.9 | 13.6 | 11.2 | 14.2 | ... | 11.2 | 10.0 | 86.0 | 78.0 | 86.0 | 211.0 | 26.4 | 18.3 | NaN | Laguna |
| 5451 | 2022/08/16 | 0300 UTC | 0.0 | 999.7 | 999.8 | 996.9 | 0.7 | 20.8 | 16.2 | 25.0 | ... | 17.2 | 16.1 | 75.0 | 61.0 | 75.0 | 253.0 | 25.7 | 12.4 | NaN | Laguna |
| 5452 | 2022/08/16 | 0400 UTC | 0.0 | 1002.5 | 1003.0 | 999.8 | 0.0 | 19.4 | 17.1 | 20.8 | ... | 17.4 | 16.2 | 88.0 | 75.0 | 86.0 | 192.0 | 25.7 | 14.5 | NaN | Laguna |
| 8303 | 2022/12/12 | 2300 UTC | 6.0 | 999.6 | 999.6 | 997.1 | 6.5 | 19.6 | 19.2 | 23.4 | ... | 22.3 | 16.8 | 98.0 | 90.0 | 98.0 | 212.0 | 25.5 | 17.2 | NaN | Laguna |
| 8304 | 2022/12/13 | 0000 UTC | 4.2 | 1001.9 | 1002.0 | 999.6 | 1.0 | 20.7 | 19.6 | 21.6 | ... | 21.0 | 19.5 | 98.0 | 94.0 | 94.0 | 209.0 | 25.5 | 11.3 | NaN | Laguna |
| 5516 | 2022/08/18 | 2000 UTC | 0.4 | 1010.2 | 1010.3 | 1008.6 | 138.3 | 14.2 | 9.3 | 14.2 | ... | 11.2 | 8.6 | 85.0 | 69.0 | 72.0 | 214.0 | 25.0 | 16.9 | NaN | Laguna |
| 5495 | 2022/08/17 | 2300 UTC | 0.0 | 1001.3 | 1001.4 | 1000.5 | 0.0 | 19.7 | 17.3 | 20.0 | ... | 17.3 | 17.1 | 86.0 | 84.0 | 86.0 | 19.0 | 24.8 | 17.0 | NaN | Laguna |
| 5760 | 2022/08/29 | 0000 UTC | 0.0 | 1023.4 | 1023.5 | 1022.2 | 0.0 | 12.6 | 5.6 | 13.1 | ... | 6.8 | 5.2 | 66.0 | 60.0 | 63.0 | 215.0 | 24.7 | 17.5 | NaN | Laguna |
| 6048 | 2022/09/10 | 0000 UTC | 0.0 | 1003.6 | 1005.5 | 1002.7 | 0.0 | 18.6 | 17.5 | 20.7 | ... | 18.2 | 17.5 | 93.0 | 86.0 | 93.0 | 198.0 | 24.3 | 12.7 | NaN | Laguna |
10 rows × 21 columns
ms_to_kmh(28.3)
101.88000000000001
Como podemos ver acima, a reportagem foi verificada
"Formação de ciclone deixa SC em alerta para rajadas de vento de até 100 km/h. Ventos devem ser mais fortes no mar, de acordo com a Defesa Civil."
laguna_df.drop(columns="Unnamed: 19",inplace=True)
laguna_df.dropna(inplace=True)
# Set an index with datetime(Data + Hora)
laguna_df['Hora UTC'] = laguna_df['Hora UTC'].str[0:2]
laguna_df['data_hora'] = pd.to_datetime(laguna_df['Data'] + " " + laguna_df['Hora UTC'])
laguna_df = laguna_df.set_index('data_hora')
mmm_variables = {
"Umidade":"UMIDADE RELATIVA DO AR, HORARIA (%)_",
"Pressão":"PRESSAO ATMOSFERICA AO NIVEL DA ESTACAO, HORARIA (mB)_",
"Temperatura":"TEMPERATURA DO AR - BULBO SECO, HORARIA (°C)_",
"Vento":"VENTO, VELOCIDADE HORARIA (m/s)_"
}
def plot_mm(station):
mmm_df = pd.merge(station_obs.reset_index(), station_params.loc[station_params['ESTACAO'] == station], how='inner', on='CODIGO (WMO)').set_index('Data')
fig = make_subplots(rows=4, cols=1,shared_xaxes=True,vertical_spacing=0.03,
subplot_titles=([key for key in mmm_variables.keys()]))
x_axis=[datetime.strptime(date, "%Y/%m/%d").date().strftime("%m/%d") for date in mmm_df.index]
for idx, var in enumerate(mmm_variables):
mmm_cols = [mmm_variables[var] + type for type in ["mean","min","max"]]
# var_df = mmm_df[mmm_cols]
fig.add_scatter(x=x_axis, y=mmm_df[mmm_cols[0]], mode='lines',name='Mean',line_width=1,row=idx+1, col=1)
fig.add_scatter(x=x_axis, y=mmm_df[mmm_cols[1]], mode='lines',name='Max',line_width=1,row=idx+1, col=1)
fig.add_scatter(x=x_axis, y=mmm_df[mmm_cols[2]], mode='lines',name="Min",line_width=1,row=idx+1, col=1)
# fig.add_scatter(x=x_axis, y=mmm_df['UMIDADE RELATIVA DO AR, HORARIA (%)_mean'], mode='lines',name='Mean',line_width=1,row=idx+1, col=1)
# fig.add_scatter(x=x_axis, y=mmm_df['UMIDADE RELATIVA DO AR, HORARIA (%)_max'], mode='lines',name='Max',line_width=1,row=idx+1, col=1)
# fig.add_scatter(x=x_axis, y=mmm_df['UMIDADE RELATIVA DO AR, HORARIA (%)_min'], mode='lines',name="Min",line_width=1,row=idx+1, col=1)
chart_label = "Médias, Máximas e Mínimas em " + station
fig.update_layout(
height=800, width=980, title_text=chart_label,showlegend=False
)
fig.update_annotations(font_size=10)
fig.show()
plot_mm("BRASILIA")
Em qual estação a variação de temperatura máx-min foi maior?
station_obs['temp_variation'] = station_obs["TEMPERATURA DO AR - BULBO SECO, HORARIA (°C)_max"] - station_obs["TEMPERATURA DO AR - BULBO SECO, HORARIA (°C)_min"]
highest_max_min = station_obs.sort_values("temp_variation",ascending=False)[[
"CODIGO (WMO)","temp_variation","TEMPERATURA DO AR - BULBO SECO, HORARIA (°C)_max","TEMPERATURA DO AR - BULBO SECO, HORARIA (°C)_min"
]]
highest_max_min = pd.merge(highest_max_min.reset_index(), station_params, how='inner', on='CODIGO (WMO)').set_index('Data')
highest_max_min.head(10)
| CODIGO (WMO) | temp_variation | TEMPERATURA DO AR - BULBO SECO, HORARIA (°C)_max | TEMPERATURA DO AR - BULBO SECO, HORARIA (°C)_min | REGIAO | UF | ESTACAO | LATITUDE | LONGITUDE | ALTITUDE | DATA DE FUNDACAO | |
|---|---|---|---|---|---|---|---|---|---|---|---|
| Data | |||||||||||
| 2022/09/14 | A547 | 27.4 | 38.6 | 11.2 | SE | MG | SAO ROMAO | -16.362778 | -45.123889 | 490.29 | 30/06/07 |
| 2022/09/11 | A547 | 26.8 | 38.6 | 11.8 | SE | MG | SAO ROMAO | -16.362778 | -45.123889 | 490.29 | 30/06/07 |
| 2022/09/10 | A547 | 25.5 | 36.3 | 10.8 | SE | MG | SAO ROMAO | -16.362778 | -45.123889 | 490.29 | 30/06/07 |
| 2022/07/30 | A547 | 25.3 | 34.4 | 9.1 | SE | MG | SAO ROMAO | -16.362778 | -45.123889 | 490.29 | 30/06/07 |
| 2022/08/06 | A547 | 25.2 | 35.9 | 10.7 | SE | MG | SAO ROMAO | -16.362778 | -45.123889 | 490.29 | 30/06/07 |
| 2022/07/29 | A547 | 25.1 | 33.3 | 8.2 | SE | MG | SAO ROMAO | -16.362778 | -45.123889 | 490.29 | 30/06/07 |
| 2022/09/13 | A547 | 25.0 | 38.4 | 13.4 | SE | MG | SAO ROMAO | -16.362778 | -45.123889 | 490.29 | 30/06/07 |
| 2022/09/04 | A547 | 24.8 | 37.1 | 12.3 | SE | MG | SAO ROMAO | -16.362778 | -45.123889 | 490.29 | 30/06/07 |
| 2022/08/08 | A547 | 23.7 | 37.2 | 13.5 | SE | MG | SAO ROMAO | -16.362778 | -45.123889 | 490.29 | 30/06/07 |
| 2022/09/15 | A547 | 23.7 | 38.9 | 15.2 | SE | MG | SAO ROMAO | -16.362778 | -45.123889 | 490.29 | 30/06/07 |
hmm = highest_max_min.groupby([highest_max_min.index,"ESTACAO"])[["temp_variation","UF"]].agg("max").reset_index().set_index('Data').sort_values("temp_variation",ascending=False)
hmm.head(10)
| ESTACAO | temp_variation | UF | |
|---|---|---|---|
| Data | |||
| 2022/09/14 | SAO ROMAO | 27.4 | MG |
| 2022/09/11 | SAO ROMAO | 26.8 | MG |
| 2022/08/13 | JATAI | 26.5 | GO |
| 2022/08/12 | ROSARIO OESTE | 25.9 | MT |
| 2022/08/10 | FORMOSA DO RIO PRETO | 25.9 | BA |
| 2022/07/30 | AGUAS VERMELHAS | 25.9 | MG |
| 2022/09/10 | SAO ROMAO | 25.5 | MG |
| 2022/09/11 | ARACUAI | 25.4 | MG |
| 2022/09/15 | CORRENTINA | 25.3 | BA |
| 2022/07/30 | SAO ROMAO | 25.3 | MG |
hmm.tail(10)
| ESTACAO | temp_variation | UF | |
|---|---|---|---|
| Data | |||
| 2022/06/06 | BURITIRAMA | 0.0 | BA |
| 2022/06/14 | EUCLIDES DA CUNHA | 0.0 | BA |
| 2022/04/18 | SALGUEIRO | 0.0 | PE |
| 2022/02/05 | ARCO VERDE | 0.0 | PE |
| 2022/06/14 | BURITIRAMA | 0.0 | BA |
| 2022/01/28 | BERTIOGA | 0.0 | SP |
| 2022/07/27 | ARCO VERDE | 0.0 | PE |
| 2022/12/23 | EUCLIDES DA CUNHA | 0.0 | BA |
| 2022/07/22 | ARCO VERDE | 0.0 | PE |
| 2022/04/24 | MARIANOPOLIS DO TO | 0.0 | TO |
plot_mm("SAO ROMAO")
Note que esta alteração brusca a partir de 6/Julho surge após um período (8 de abril a 6/Julho) sem dados. Valeria a pena excluir a possibilidade de nenhum erro de leitura, ou qquer outro outlier.
plot_mm("JATAI")
Parece haver um padrão nestas cidades de maior variação... Onde ficam?
cidades_maior_variacao = ["SAO ROMAO","JATAI","ROSARIO OESTE","FORMOSA DO RIO PRETO","AGUAS VERMELHAS","ARACUAI","CORRENTINA"]
station_params.loc[station_params['ESTACAO'].isin(cidades_maior_variacao)]
| REGIAO | UF | ESTACAO | CODIGO (WMO) | LATITUDE | LONGITUDE | ALTITUDE | DATA DE FUNDACAO | |
|---|---|---|---|---|---|---|---|---|
| 13 | CO | GO | JATAI | A016 | -17.923622 | -51.717467 | 670.08 | 23/05/07 |
| 96 | CO | MT | ROSARIO OESTE | A944 | -14.828889 | -56.441944 | 195.00 | 30/05/19 |
| 116 | NE | BA | CORRENTINA | A416 | -13.332500 | -44.617500 | 551.71 | 09/11/07 |
| 146 | NE | BA | FORMOSA DO RIO PRETO | A452 | -11.052222 | -45.200833 | 488.00 | 02/06/16 |
| 385 | SE | MG | SAO ROMAO | A547 | -16.362778 | -45.123889 | 490.29 | 30/06/07 |
| 387 | SE | MG | AGUAS VERMELHAS | A549 | -15.751536 | -41.457787 | 754.07 | 09/09/07 |
| 403 | SE | MG | ARACUAI | A566 | -16.848889 | -42.035278 | 308.00 | 19/05/17 |
MV_Map = leafmap.Map(center=[-15, -48], zoom=4)
mv_df = station_params.loc[station_params['ESTACAO'].isin(cidades_maior_variacao)].reset_index()
MV_Map.add_points_from_xy(
mv_df,
x="LONGITUDE",
y="LATITUDE",
#color_column='region',
icon_names=['gear', 'map', 'leaf', 'globe'],
spin=True,
add_legend=True
)
MV_Map
Map(center=[-15, -48], controls=(ZoomControl(options=['position', 'zoom_in_text', 'zoom_in_title', 'zoom_out_t…
import geopandas as gpd
from shapely.geometry import Point, Polygon
from folium import Choropleth, Circle, Marker
from folium.plugins import HeatMap, MarkerCluster
import math
ps_border = ["JEREMOABO","CURACA","SAO JOAO DO PIAUI","CANTO DO BURITI","ALVORADA DO GURGUEIA","BALSAS","DIANOPOLIS","POSSE","CHAPADA GAUCHA","MONTALVANIA","VITORIA DA CONQUISTA","ITIRUCU","ITABERABA","FEIRA DE SANTANA","RIBEIRA DO AMPARO"]
temp_df = station_params.loc[station_params['ESTACAO'].isin(ps_border)]
ps_df = pd.DataFrame()
for st in ps_border:
row = temp_df.loc[temp_df["ESTACAO"] == st]
ps_df = pd.concat([ps_df,row])
ps_df
| REGIAO | UF | ESTACAO | CODIGO (WMO) | LATITUDE | LONGITUDE | ALTITUDE | DATA DE FUNDACAO | |
|---|---|---|---|---|---|---|---|---|
| 145 | NE | BA | JEREMOABO | A450 | -10.080833 | -38.345833 | 261.00 | 13/08/15 |
| 143 | NE | BA | CURACA | A448 | -9.001389 | -39.912500 | 370.00 | 20/08/15 |
| 210 | NE | PI | SAO JOAO DO PIAUI | A331 | -8.364444 | -42.252500 | 231.00 | 26/08/07 |
| 221 | NE | PI | CANTO DO BURITI | A365 | -8.118056 | -42.975833 | 312.07 | 12/06/10 |
| 212 | NE | PI | ALVORADA DO GURGUEIA | A336 | -8.441667 | -43.865556 | 261.26 | 17/11/07 |
| 167 | NE | MA | BALSAS | A204 | -7.455556 | -46.027500 | 271.03 | 26/10/07 |
| 315 | N | TO | DIANOPOLIS | A038 | -11.594444 | -46.847222 | 727.87 | 30/08/08 |
| 14 | CO | GO | POSSE | A017 | -14.089167 | -46.366389 | 830.00 | 18/04/07 |
| 386 | SE | MG | CHAPADA GAUCHA | A548 | -15.300278 | -45.617500 | 873.20 | 22/06/07 |
| 364 | SE | MG | MONTALVANIA | A526 | -14.408333 | -44.404167 | 519.52 | 26/06/07 |
| 114 | NE | BA | VITORIA DA CONQUISTA | A414 | -14.886389 | -40.801389 | 879.38 | 01/06/07 |
| 109 | NE | BA | ITIRUCU | A407 | -13.527828 | -40.119752 | 757.42 | 09/02/03 |
| 110 | NE | BA | ITABERABA | A408 | -12.524167 | -40.299722 | 250.11 | 29/01/03 |
| 113 | NE | BA | FEIRA DE SANTANA | A413 | -12.196111 | -38.967500 | 229.64 | 26/05/07 |
| 149 | NE | BA | RIBEIRA DO AMPARO | A458 | -11.058611 | -38.444167 | 182.00 | 20/09/18 |
ps_codes = ps_df['CODIGO (WMO)'].values
ps_codes
array(['A450', 'A448', 'A331', 'A365', 'A336', 'A204', 'A038', 'A017',
'A548', 'A526', 'A414', 'A407', 'A408', 'A413', 'A458'],
dtype=object)
ps_data = station_obs.loc[station_obs['CODIGO (WMO)'].isin(ps_codes)]
ps_max_temps = ps_data.groupby("CODIGO (WMO)")[["TEMPERATURA MÁXIMA NA HORA ANT. (AUT) (°C)_max"]].agg("max")
ps_max_temps
| TEMPERATURA MÁXIMA NA HORA ANT. (AUT) (°C)_max | |
|---|---|
| CODIGO (WMO) | |
| A017 | 36.3 |
| A038 | 36.0 |
| A204 | 39.1 |
| A331 | 39.1 |
| A365 | 38.6 |
| A407 | 33.0 |
| A413 | 36.5 |
| A414 | 33.4 |
| A450 | 36.4 |
| A458 | 37.7 |
| A526 | 34.5 |
| A548 | 36.2 |
lats = ps_df['LATITUDE'].values
longs = ps_df['LONGITUDE'].values
stations = ps_df['CODIGO (WMO)'].values
ps_points = [ Point(lats[i],longs[i]) for i in range(0,len(lats))]
ps_polygon = Polygon(zip(longs, lats))
ps_gpd = gpd.GeoDataFrame(index=[0], crs='epsg:4326', geometry=[ps_polygon])
ps_gpd
| geometry | |
|---|---|
| 0 | POLYGON ((-38.34583 -10.08083, -39.91250 -9.00... |
tm = ps_max_temps['TEMPERATURA MÁXIMA NA HORA ANT. (AUT) (°C)_max'].mean()
t_df = pd.DataFrame(columns=['CODIGO (WMO)','TEMPERATURA MÁXIMA NA HORA ANT. (AUT) (°C)_max'])
for index, row in ps_df.iterrows():
row_df = pd.DataFrame([[row['CODIGO (WMO)'], tm]],columns=['CODIGO (WMO)','TEMPERATURA MÁXIMA NA HORA ANT. (AUT) (°C)_max'])
t_df = pd.concat([t_df,row_df])
t_df.set_index("CODIGO (WMO)",drop=True,inplace=True)
prompt_df = pd.merge(t_df, ps_max_temps,how='outer',left_index=True, right_index=True)
prompt_df
| TEMPERATURA MÁXIMA NA HORA ANT. (AUT) (°C)_max_x | TEMPERATURA MÁXIMA NA HORA ANT. (AUT) (°C)_max_y | |
|---|---|---|
| CODIGO (WMO) | ||
| A017 | 36.4 | 36.3 |
| A038 | 36.4 | 36.0 |
| A204 | 36.4 | 39.1 |
| A331 | 36.4 | 39.1 |
| A336 | 36.4 | NaN |
| A365 | 36.4 | 38.6 |
| A407 | 36.4 | 33.0 |
| A408 | 36.4 | NaN |
| A413 | 36.4 | 36.5 |
| A414 | 36.4 | 33.4 |
| A448 | 36.4 | NaN |
| A450 | 36.4 | 36.4 |
| A458 | 36.4 | 37.7 |
| A526 | 36.4 | 34.5 |
| A548 | 36.4 | 36.2 |
m_states = folium.Map(location=(2, -40), zoom_start=4, tiles="cartodb positron")
folium.Choropleth(
geo_data="../data/Brazil.json",
data=code_df,
columns=["UF", "TEMPERATURA DO AR - BULBO SECO, HORARIA (°C)_mean"],
key_on="feature.properties.UF",
fill_color="RdYlGn_r",
fill_opacity=0.8,
line_opacity=0.3,
nan_fill_color="white",
).add_to(m_states)
# Mark the locations of PS
for index, row in ps_df.iterrows():
popup_text = row['ESTACAO'] + ": " + str(t_df.loc[row['CODIGO (WMO)']][0])
folium.Marker(
location=[row['LATITUDE'], row['LONGITUDE']],
popup=popup_text,
icon=folium.Icon(color="red"),
).add_to(m_states)
# The PS Polygon
sim_geo = gpd.GeoSeries(ps_gpd["geometry"]).simplify(tolerance=0.001)
geo_j = sim_geo.to_json()
geo_j = folium.GeoJson(data=geo_j, style_function=lambda x: {"fillColor": "orange"})
geo_j.add_to(m_states)
# Again, the stations with highest vairance in temperatures
for index, row in mv_df.iterrows():
folium.Marker(
location=[row['LATITUDE'], row['LONGITUDE']],
popup=row['ESTACAO'],
icon=folium.Icon(color="blue"),
).add_to(m_states)
m_states
Acima, uma versão simplificada do Polígono das Secas com ALGUMAS cidades em vermelho que mais se aproximam do que se convencio nou.
Em azul, eu reapresentei as cidades com maiores variações de temperaturas diárias.
A despeito das técnicas de programação usadas, o dataset é bem interessante para a estudo e prática de tratamento e apresentação de dados
Algumas sugestões de enriquecimento incluem análise de Correlação, inclusive com ALTITUDE, uma variável não observada aqui.